#pragma once
#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include<time.h>
#include<errno.h>
#include <cstdarg>
#include<vector>
#include <sys/wait.h>
#define FILENAME "myfifo"
#define Logname "log.txt"
#define MODE 0666
#define SIZE 1024
#define INFO "Info"
#define WARNING "Warning"
#define  FATAL "Fatal"
#define  DEBUG "Debug"
#define PRONUM 2
using namespace std;
enum Fail
{
    MKFIFO_ERR = 1,
    FORK_ERR,
    CREATSHM_ERR,
    GETSHM_ERR,
    DELSHM_ERR,
};

//错误等级
enum ErrorLevel
{
    Info = 1,
    Warning,
    Fatal,
    Debug
};
//接收输出的文件
enum PMethod
{
    Screen = 1,//输出到屏幕
    OneFile ,//输出到一个文件上
    ClassFile//分类输出到多个文件中
};
class channel
{
public:
    channel(int fd,int pid,string& proname)
    :_fd(fd)
    ,_pid(pid)
    ,_proname(proname)
    {
        ;
    }
    int _fd;//存管道fd
    int _pid;//存子进程pid
    string _proname;//进程名
};
// 实现自动创建和销毁管道文件
class Init
{
public:
    Init()
    {
        int ret = mkfifo(FILENAME, MODE);
        if (ret == -1)
        {
            perror("mkfifo");
            exit(MKFIFO_ERR);
        }
    }
    ~Init()
    {
        unlink(FILENAME);
    }
};
class Log
{
public:
    Log(int method = Screen)
    :printmethod(method)
    {
        ;
    }
    string leveltostring(int level)
    {
        switch (level)
        {
            case Info:
                return "Info";
            case Warning:
                return "Warning";
            case Fatal:
                return "Fatal";
            case Debug:
                return "Debug";
            default: 
                return "None";    
        }
    }
    //日志信息
    //枚举常量版本
    void operator()(int level, const char *format, ...)
    {
        char leftbuffer[SIZE];
        time_t t = time(NULL);
        struct tm * ltime = localtime(&t);
        //默认部分 事件等级和时间
        snprintf(leftbuffer,sizeof(leftbuffer),"%s [%d %d %d %d:%d]",leveltostring(level).c_str(),
        ltime->tm_year+1900,ltime->tm_mon+1,ltime->tm_mday,ltime->tm_hour,ltime->tm_min);

        //可变部分
        char rightbuffer[SIZE];
        va_list s;
        va_start(s,format);
        vsnprintf(rightbuffer,sizeof(rightbuffer),format,s);
        // printf("%s %s\n",leftbuffer,rightbuffer);
        char Logbuffer[SIZE*2];
        snprintf(Logbuffer,sizeof(Logbuffer),"%s %s",leftbuffer,rightbuffer);
        LogPrint(level,Logbuffer);
    }
    // void logmessage(int level, const char *format, ...)
    // {
    //     char leftbuffer[SIZE];
    //     time_t t = time(nullptr);
    //     struct tm * ltime = localtime(&t);
    //     //默认部分 事件等级和时间
    //     snprintf(leftbuffer,sizeof(leftbuffer),"%s [%d %d %d %d:%d]",leveltostring(level).c_str(),
    //     ltime->tm_year+1900,ltime->tm_mon+1,ltime->tm_mday,ltime->tm_hour,ltime->tm_min);

    //     //可变部分
    //     char rightbuffer[SIZE];
    //     va_list s;
    //     va_start(s,format);
    //     vsnprintf(rightbuffer,sizeof(rightbuffer),format,s);
    //     // printf("%s %s\n",leftbuffer,rightbuffer);
    //     char Logbuffer[SIZE*2];
    //     snprintf(Logbuffer,sizeof(Logbuffer),"%s %s",leftbuffer,rightbuffer);
    //     LogPrint(level,Logbuffer);
    // }
    void PrintOnefile( const char *filename,string& lbuffer)
    {
        lbuffer+='\n';
        int fd = open(filename, O_CREAT|O_APPEND|O_WRONLY,0666);
        if(fd < 0)
            return;
         write(fd,lbuffer.c_str(),lbuffer.size());   
    }
    void PrintClassFile(int level,string& lbuffer)
    {
        string filename = Logname;//将不同错误信息分流到对应的文件
        filename += ".";
        filename += leveltostring(level);
        PrintOnefile(filename.c_str(),lbuffer);
    }
    void LogPrint(int level,string lbuffer)
    {
        switch(printmethod)
        {
            case Screen://输出到屏幕
               cout<<lbuffer<<endl;
                break;
            case OneFile: //输出到一个文件上
                PrintOnefile(Logname,lbuffer);
                break;
            case ClassFile:
                PrintClassFile(level,lbuffer);
                break;
        }
    }
private:
    int printmethod;
};
